-- local gallop = require "QGMainWindow"
require"luaFDTD3D"
local nl = require"luaNumeric"
-- local rcwa = require"luaRCWA"
-- local plot = require "Q2DViewerEx"
require "unity"
local lfs = require"lfs"

-- require "Q2DViewer"
-- require "Q2DViewerEx"
-----------------------------------------------------------------------------
--初始化参数
local NFPost={
     nheader = 7;  
     nbandheader=1;
     data = {}; -- file to table
     str = {};   -- file to string
     listdata = {};
     npts = 0;
     nfields = 0;
     xx = nl.new_vector();
     yy = nl.new_vector();
     zz = nl.new_vector();
     ds = nl.new_vector();
     labels = {};
     xx_idx={};
     yy_idx={};
     zz_idx={};
     freq_idx={};
};
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--创建表和创建元表
function NFPost:new (o)
	o = o or {};
	self.__index = self;	
	setmetatable(o,self)
	-- print( "RCSPost new" )
	return o;
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--导入数据
function NFPost:read_from_file(path)		

	-- local fields = self:create_view();

	print(path);
	self.path = path;
	self.data = file2table( path,"\t")	
	self.str = file2StrTable( path,"\t")	

	local nheader = self.nheader;
	self.npts = #self.str - nheader;
	self.nfields = (#self.str[nheader]-4)/2;
	self.labels = self.str[nheader];
	
	print( "pts: ",self.npts)
	print( "fields: ",self.nfields)
	
	self.xx = nl.new_vector();
	self.yy = nl.new_vector();
	self.zz = nl.new_vector();
	self.dss = nl.new_vector();
	self.xx:reserve(self.npts)
	self.yy:reserve(self.npts)
	self.zz:reserve(self.npts)
	self.dss:reserve(self.npts)
	self.fields = {};
	self.headers = {};
	for jj=1,self.nfields do
		self.fields[jj] = nl.new_cvector();
		self.fields[jj]:reserve(self.npts)
		self.headers[jj]=self.labels[4+jj*2-1];
	end
	 for ii=1,self.npts do
		 self.xx:push_back(self.data[ii+nheader][1]);
		 self.yy:push_back(self.data[ii+nheader][2]);
		 self.zz:push_back(self.data[ii+nheader][3]);
		 self.dss:push_back(self.data[ii+nheader][4]);
		 
		 for jj=1,self.nfields do	
			 -- print( self.data[ii+nheader+1][4+jj*2-1],self.data[ii+nheader+1][4+jj*2] )
			local  data = nl.polar(self.data[ii+nheader][4+jj*2-1],self.data[ii+nheader][4+jj*2] )
			self.fields[jj]:push_back(data)
		 end
	 end
	
	assert( self.npts>0, "points size empty" )
	assert( self.nfields>0, "fields size empty" )
	
	print( "Import fields succesfully, points size:".. self.npts .. ' fields size:' .. self.nfields );
	
	self:parsers();
	
	self:ft();
	
	-- self:create_fields_view();

end	
-----------------------------------------------------------------------------

--============================================================
--导出图片
function NFPost:save_kpngs(dir)	

	for ii=1,#self.freq_idx do
		local freqList = nl.new_svector();
		freqList:add(self.freq_idx[ii]);
		for jj=1,#self.fields_type_idx do
			local ftList = nl.new_svector();
			ftList:add(self.fields_type_idx[jj]);
			self:update_selected_index_to_ui(freqList,ftList);	
			self:save_kpng( dir..'/kband('..self.freq_idx[ii]..'-'..self.fields_type_idx[jj]..').png' );
		end
	end
end
--============================================================



-----------------------------------------------------------------------------
--导入数据
function NFPost:read_band_from_file_gui(path)	
	self:update_settings_from_ui();
	self:read_band_from_file(path);
	self:create_band_fields_view();
	self:update_index_list_to_ui();
end

-----------------------------------------------------------------------------
--导入数据
function NFPost:read_band_from_file(path)	
	print(path);
	self.band_path = path;
	self.band_data = file2table( path,"\t")	
	self.band_str = file2StrTable( path,"\t")	
	
	local nbandheader = self.nbandheader;
	self.nbandpts = #self.band_data - nbandheader;
	self.nkfields = (#self.band_str[nbandheader]-2);
	self.klabels = self.band_str[nbandheader];
	self.nfields = self.nkfields;
	
	print( "kpts: ",self.nbandpts)
	print( "kfields: ",self.nkfields)
	
	self.Gxx = nl.new_vector();
	self.Gyy = nl.new_vector();
	self.Gzz = nl.new_vector();
	self.Gxx:reserve(self.nbandpts)
	self.Gyy:reserve(self.nbandpts)
	self.Gzz:reserve(self.nbandpts)
	
	self.kfields = {};
	self.headers = {};
	for jj=1,self.nfields do
		self.kfields[jj] = nl.new_cvector();
		self.kfields[jj]:reserve(self.nbandpts)
		self.headers[jj]=self.klabels[2+jj];
	end
	 for ii=1,self.nbandpts do
		 self.Gxx:push_back(self.band_data[ii+nbandheader][1]);
		 self.Gyy:push_back(self.band_data[ii+nbandheader][2]);
		 self.Gzz:push_back(0);
		 -- local max = 0;
		 for jj=1,self.nfields do	
			local  data = nl.polar(self.band_data[ii+nbandheader][2+jj],0)
			-- max = math.max( max, nl.abs(data) )
			self.kfields[jj]:push_back(data)
		 end
		 -- print( max )
	 end
	 
	 self:parsers_band();
end
-----------------------------------------------------------------------------

-----------------------------------------------------------------------------
--导入数据
function NFPost:create_band_fields_view()
	self.kFieldsViews = {};
	self.nearFieldsViews = nil;
	for jj=1,self.nkfields do
		print( "create view: f="..(self.freqs[jj]), "fields type="..(self.fields_types[jj]))

		local kfields = self:create_view();
		for k,v in pairs(self.Gxx) do
			kfields:insert(self.Gxx[k], self.Gyy[k], 0, nl.abs(  self.kfields[ jj ][k]  ) )				
		end
		local dm = kfields:max_amplitude()
		print( "dm:",dm)
		kfields:GLColorMap():min(0);
		kfields:GLColorMap():max(dm/2.0);
		self.kFieldsViews[jj] = kfields;
	end
end
-----------------------------------------------------------------------------

function NFPost:ft()
	print( "ft" );
	local Gx = pi/self.px/mm;
	local Gy = pi/self.py/mm;
	self.Gx = nl.LinearSpace(-Gx,Gx,self.nkx);
	self.Gy = nl.LinearSpace(-Gy,Gy,self.nky);
	self.Gxx,self.Gyy = nl.grids(self.Gx,self.Gy);
	self.kfields = {}
	for jj=1,self.nfields do	
		print( "fourier transform: freq="..self.freqs[jj] ,"fields type=:" .. self.fields_types[jj] )
		self.kfields[jj] = nl.new_cvector(#self.Gxx);
		nl.ft2D(self.xx * mm,self.yy * mm,self.fields[jj],self.Gxx,self.Gyy,self.dss * mm * mm,self.kfields[jj])
	end
	
	local kpath = getFilename(self.path) .. ".band/";
	lfs.mkdir(kpath);
	
	local file = io.open(kpath.."/band.txt", "w")
	file:write( "kx\tky\t" );
	for jj=1,self.nfields do	
		file:write( "freq["..self.freqs[jj],"]_" .. self.fields_types[jj] .."\t"  )
	end
	file:write(  "\n" );


	for ii=1,#self.Gxx do
		file:write( self.Gxx[ii], "\t" );
		file:write( self.Gyy[ii], "\t" );
		for jj=1,self.nfields do	
			file:write( nl.abs(self.kfields[jj][ii]), "\t" )
		end
		file:write(  "\n" );
	end
	file:close()
end

function Set(list)
	local set1 = {}
	for _,v in pairs(list) do set1[tostring(v)] = true; end
	
	local set2 = {}
	for k,v in pairs(set1) do table.insert( set2, k ); end
	return set2;
end
function NFPost:get_idx()
	self.xx_idx = Set (self.xxs );
	self.yy_idx = Set (self.yys );
	self.zz_idx = Set (self.zzs );
	self.freq_idx = Set (self.freqs );
	self.fields_type_idx = Set(self.fields_types);
	table.sort(self.xx_idx,function (a,b) return tonumber(a)<tonumber(b) end )
	table.sort(self.yy_idx,function (a,b) return tonumber(a)<tonumber(b) end )
	table.sort(self.zz_idx,function (a,b) return tonumber(a)<tonumber(b) end )
	table.sort(self.freq_idx,function (a,b) return tonumber(a)<tonumber(b) end )
end

function NFPost:parsers()

	-- 科学计数
	number = "[ ]*[+-]?%d+[.]?%d*[Ee+-]*%d*";
	
	self.xxs = {};
	for kk,vv in pairs (self.xx) do
		self.xxs[ kk ] = tostring(vv)
	end
	self.yys = {};
	for kk,vv in pairs (self.yy) do
		self.yys[ kk ] = tostring(vv)
	end
	self.zzs = {};
	for kk,vv in pairs (self.zz) do
		self.zzs[ kk ] = tostring(vv)
	end
		
	self.freqs = {}
	self.fields_types = {}
	self.freq_fts_idx = {}
	
	for jj=1,self.nfields do
		local label = self.labels[4+2*jj-1];
		self.freqs[jj] =  string.match(label, number)
		self.fields_types[jj] = string.match(label, '.*[_](.*)')
		assert( self.freqs[jj], "freqs parsers error")
		assert( self.fields_types[jj], "fields_type parsers error")
		self.freq_fts_idx[ self.freqs[jj]..self.fields_types[jj] ] = jj;
	end
	
	self:get_idx()
	
end

function NFPost:parsers_band()

	-- 科学计数
	number = "[ ]*[+-]?%d+[.]?%d*[Ee+-]*%d*";
			
	self.freqs = {}
	self.fields_types = {}
	self.freq_fts_idx = {}
	
	for jj=1,self.nkfields do
		local label = self.klabels[2+jj];
		self.freqs[jj] =  string.match(label, number)
		self.fields_types[jj] = string.match(label, '.*[_](.*)')
		assert( self.freqs[jj], "freqs parsers error")
		assert( self.fields_types[jj], "fields_type parsers error")
		self.freq_fts_idx[ self.freqs[jj]..self.fields_types[jj] ] = jj;
	end
	
	self.freq_idx = Set (self.freqs );
	self.fields_type_idx = Set(self.fields_types);
	table.sort(self.freq_idx,function (a,b) return tonumber(a)<tonumber(b) end )
end

function NFPost:create_fields_view()
	self.nearFieldsViews = {};
	self.kFieldsViews = {};
	for jj=1,self.nfields do
		print( "create view: f="..(self.freqs[jj]), "fields type="..(self.fields_types[jj]))
		-- local fields = Geometry.NewTrigScalarFields3D();
		local fields = self:create_view();
		for k,v in pairs(self.xx) do
			fields:insert(self.xx[k], self.yy[k], self.zz[k], nl.real(  self.fields[ jj ][k]  ) )				
		end
		local dm = fields:max_amplitude()
		fields:GLColorMap():min(-dm/10);
		fields:GLColorMap():max(dm/10);
		self.nearFieldsViews[jj]=fields;
		
		local kfields = self:create_view();
		for k,v in pairs(self.Gxx) do
			kfields:insert(self.Gxx[k], self.Gyy[k], 0, nl.abs(  self.kfields[ jj ][k]  ) )				
		end
		local dm = kfields:max_amplitude()
		kfields:GLColorMap():min(0);
		kfields:GLColorMap():max(dm/2.0);
		self.kFieldsViews[jj] = kfields;
	end
end

function NFPost:clear_curves()
	assert(self.view, "You should creat a viewer first" )
	assert(self.mw:hasView(self.view)==true,"The viewer is closed!")
	self.mw:activeView(self.view);
	self.view:clearGraphs()
	self.view:rescaleAxes();
end
function NFPost:get_view(freqs,fts)
	assert(#freqs == 1 , "Selected frequency size error");
	assert(#fts == 1 , "Selected fields type size error");	
	-- assert(self.nearFields , "Nearfields container error");		
	assert(self.kFieldsViews , "Nearfields container error");		
	local ftt=fts[1];
	local ff = freqs[1];
	print("freq="..ff, "fieldstype="..ftt);
	local idx = ff..ftt;
	local jj = self.freq_fts_idx[ idx ];
	if self.nearFieldsViews then
		return self.nearFieldsViews[jj], self.kFieldsViews[jj]
	else
		return self:create_view(), self.kFieldsViews[jj]
	end
	
	-- return self.kFieldsViews[jj]
end
function NFPost:add_curves(freqs,fts)

	assert(#freqs == 1 , "Selected frequency size error");
	assert(#fts == 1 , "Selected fields type size error");	
	assert(self.nearFields , "Nearfields container error");	
	
	
	local ftt=fts[1];
	local ff = freqs[1];
	print("freq="..ff, "fieldstype="..ftt);
	local idx = ff..ftt;
	local jj = self.freq_fts_idx[ idx ];
	for k,v in pairs(self.xx) do
		self.nearFields:insert(self.xx[k], self.yy[k], self.zz[k], nl.real(  self.fields[ jj ][k]  ) )				
	end
	local dm = self.nearFields:max_amplitude()
	self.nearFields:GLColorMap():min(-dm/10);
	self.nearFields:GLColorMap():max(dm/10);
	
	
	for k,v in pairs(self.Gxx) do
		self.kFields:insert(self.Gxx[k], self.Gyy[k], 0, nl.abs(  self.kfields[ jj ][k]  ) )				
	end
	local dm = self.kFields:max_amplitude()
	self.kFields:GLColorMap():min(0);
	self.kFields:GLColorMap():max(dm/2.0);

--[[
	for x,xx in pairs(self.xx_idx) do
		for y,yy in pairs(self.yy_idx) do
			for z,zz in pairs(self.zz_idx) do
					idx = xx .." ";
					idx = idx .. yy .." ";
					idx = idx .. zz .." ";
					idx = idx .. ftt .." ";
					idx = idx .. ff;		
					-- print( x,y,z,idx,xx,yy,zz)
					 -- print( nl.abs(  self.listdata[ idx ].fields )  )
					self.nearFields:insert(tonumber(xx), tonumber(yy), tonumber(zz), nl.real(  self.listdata[ idx ].fields  )/2 )				
			end
		end
	end
--]]	
end







return NFPost;


